package org.dromara.common.core.utils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：线程相关工具类.
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Threads {

    /**
     * sleep等待,单位为毫秒
     * 暂停当前线程的执行一段时间
     *
     * @param milliseconds 暂停的时长，单位为毫秒
     */
    public static void sleep(long milliseconds) {
        try {
            // 使用Thread.sleep使当前线程暂停指定的毫秒数
            Thread.sleep(milliseconds);
        } catch (InterruptedException e) {
            // 如果线程在暂停期间被中断，则提前返回
            return;
        }
    }

    /**
     * 停止线程池
     * 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
     * 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
     * 如果仍然超時，則強制退出.
     * 另对在shutdown时线程本身被调用中断做了处理.
     *
     * 关闭给定的线程池，并等待其终止。
     * 如果线程池已经关闭，则此方法不执行任何操作。
     *
     * @param pool 要关闭的线程池
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool) {
        // 检查线程池是否非空且尚未关闭
        if (pool != null && !pool.isShutdown()) {
            // 关闭线程池，不再接受新任务
            pool.shutdown();
            try {
                // 等待线程池在120秒内终止
                if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                    // 如果线程池未能在规定时间内终止，发送终止信号
                    pool.shutdownNow();
                    // 再次等待线程池终止
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS)) {
                        // 记录线程池未能终止的信息
                        log.info("Pool did not terminate");
                    }
                }
            } catch (InterruptedException ie) {
                // 如果等待过程中线程被中断，发送终止信号
                pool.shutdownNow();
                // 标记当前线程为中断状态
                Thread.currentThread().interrupt();
            }
        }
    }

    /**
     * 打印线程异常信息
     */
    public static void printException(Runnable r, Throwable t) {
        // 如果没有直接抛出异常，并且任务是Future类型
        if (t == null && r instanceof Future<?>) {
            try {
                // 将任务强制转换为Future类型，并检查是否已完成
                Future<?> future = (Future<?>) r;
                if (future.isDone()) {
                    // 如果任务已完成，尝试获取结果，以便触发可能的异常
                    future.get();
                }
            } catch (CancellationException ce) {
                // 如果任务被取消，将异常对象赋值给t
                t = ce;
            } catch (ExecutionException ee) {
                // 如果任务执行中抛出了异常，获取并赋值给t
                t = ee.getCause();
            } catch (InterruptedException ie) {
                // 如果线程在等待任务完成时被中断，重新设置中断状态
                Thread.currentThread().interrupt();
            }
        }
        if (t != null) {
            log.error(t.getMessage(), t);
        }
    }
}
